/**
 * JDOを用いてデータストアにアクセスするDAO
 * このDAOではCRUDの動作をサポートしている。
 * 書き方は以下のようにtry-finally構文を利用する。
 * GoogleのデータベースであるデータストアはKey-Valueストアなので
 * RDBMSと違い可能なことがそう多くない。
 * トランザクションはキーによって構成されている。
 * 成功なら全て成功か失敗なら全て失敗のどちらかになる。
 */

package sample.dao;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.jdo.Query;

import com.google.appengine.api.datastore.Key;

import sample.dao.PMF;
import sample.dto.Child;
import sample.dto.Parent;

/**
 * @author fujimura
 *
 */
public class JDO {
	
	//***永続化に必要***//
	PersistenceManager PersistenceManager;
	
	//Create
	/**
	 * @
	 */
	public void Create(Parent Parent,Child Child){
		PersistentetService();
		Parent.setChildList(Arrays.asList(Child));
		//***トランザクションの開始***//
		Transaction transaction = PersistenceManager.currentTransaction();
		transaction.begin();
		try{
			PersistenceManager.makePersistent(Parent);
			//***コミット***//
			transaction.commit();
		}finally{
			//***トランザクションにエラーが発生した場合ロールバックを行う***//
			if (transaction.isActive()) {
				transaction.rollback();
			}
			PersistenceManager.close();
		}
	}
	
	//Read
	/**
	 * データストアからエンティティグループのデータを取得するメソッド
	 * @author fujimura
	 * @return Parentのカラムの全てのデータ
	 * @exception Keyが存在しなかった場合
	 * 
	 */
	@SuppressWarnings("unchecked")
	public List<Parent> getEntityGroup(){
		PersistentetService();
		ArrayList<Parent> ParentList = new ArrayList<Parent>();
		List<Parent> result=null;
		try{
			Query query = PersistenceManager.newQuery(Parent.class);
			result=(List<Parent>)query.execute();
			PersistenceManager.detachCopyAll(result);
		}catch (JDOObjectNotFoundException e) {
			return ParentList;
		}finally{
			PersistenceManager.close();
		}
		for(Parent Parent:result){
			ParentList.add(new Parent(Parent.getKey(),Parent.getValue(),Parent.getChildList()));
		}
		return ParentList;
	}

	@SuppressWarnings("unchecked")
	public List<Parent> getEntity(String Valu){
		PersistentetService();
		ArrayList<Parent> ParentList = new ArrayList<Parent>();
		List<Parent> result=null;
		try{
//			Query query = PersistenceManager.newQuery(Parent.class);
//			query.setFilter("Value == Valu");
//			query.declareParameters("String Valu");
//			result=(List<Parent>)query.execute(Valu);
			
//			//***JDOQLを用いた取得***//
//			//***注意すべきところはselect fromや
//			//***StoreDataDto.class.getName()で取得したクラス名やwhere句の後に１つ空白があること***//
//			//***これを入れないとJDOQLにならず、文字が続いてしまうため***//
			String JDOQLSample="select from "+ Parent.class.getName()+" where Value == Valu "+"parameters String Valu";
//			//***JDOQLを用いた方法だとデータストアへは以下のコードになる***//
			result = (List<Parent>)PersistenceManager.newQuery(JDOQLSample).execute(Valu);
			
			PersistenceManager.detachCopyAll(result);
		}catch (JDOObjectNotFoundException e) {
			return ParentList;
		}finally{
			PersistenceManager.close();
		}
		for(Parent Parent:result){
			ParentList.add(new Parent(Parent.getKey(),Parent.getValue(),Parent.getChildList()));
		}
		return ParentList;
	}
	
	//UpDate
	public void UpDateParent(Parent Parent){
		PersistentetService();
		Transaction transaction = PersistenceManager.currentTransaction();
		transaction.begin();
		try{
			Parent UpDateParent = PersistenceManager.getObjectById(Parent.class,Parent.getKey());
			UpDateParent.setValue(Parent.getValue());
			transaction.commit();
		}finally{
			if (transaction.isActive()) {
				transaction.rollback();
			}
			PersistenceManager.close();
		}
	}
	
	public void UpDateChild(Child Child){
		PersistentetService();
		Transaction transaction = PersistenceManager.currentTransaction();
		transaction.begin();
		try{
			Child UpDateChild = PersistenceManager.getObjectById(Child.class,Child.getChildKey());
			UpDateChild.setChildValue1(Child.getChildValue1());
			UpDateChild.setChildValue2(Child.getChildValue2());
			transaction.commit();
		}finally{
			if (transaction.isActive()) {
				transaction.rollback();
			}
			PersistenceManager.close();
		}
	}
	
	public void UpDateEntityGroup(Parent Parent,Child Child){
		PersistentetService();
		Transaction transaction = PersistenceManager.currentTransaction();
		transaction.begin();
		try{
			Parent UpDateParent = PersistenceManager.getObjectById(Parent.class,Parent.getKey());
			UpDateParent.setValue(Parent.getValue());
			List<Child> UpDateChildList = UpDateParent.getChildList();
			for(Child UpDateChild:UpDateChildList){
				if(UpDateChild.getChildKey().equals(Child.getChildKey())){
					UpDateChild.setChildValue1(Child.getChildValue1());
					UpDateChild.setChildValue2(Child.getChildValue2());
				}
			}
			transaction.commit();
		}finally{
			if (transaction.isActive()) {
				transaction.rollback();
			}
			PersistenceManager.close();
		}
	}
	
	//Delete
	/**
	 * ルートキーを削除するとカスケードされて
	 * エンティティグループ全てが削除されてしまう
	 */
	public void DeleteEntityGroup(Key RootKey){
		PersistentetService();
		Transaction transaction = PersistenceManager.currentTransaction();
		transaction.begin();
		try{
			//***引数と同じキーを特定***//
			Parent DeleteEntityGroup = PersistenceManager.getObjectById(Parent.class,RootKey);
			PersistenceManager.deletePersistent(DeleteEntityGroup);
			transaction.commit();
		}finally{
			if (transaction.isActive()) {
				transaction.rollback();
			}
			PersistenceManager.close();
		}
	}
	
	public void DeleteChild(Key ChildKey){
		PersistentetService();
		Transaction transaction = PersistenceManager.currentTransaction();
		transaction.begin();
		try{
			Child DeleteChild = PersistenceManager.getObjectById(Child.class,ChildKey);
			PersistenceManager.deletePersistent(DeleteChild);
			transaction.commit();
		}finally{
			if (transaction.isActive()) {
				transaction.rollback();
			}
			PersistenceManager.close();
		}
	}
	
	protected void PersistentetService(){
		if(PersistenceManager == null){
			PersistenceManager = PMF.get().getPersistenceManager();
		}
		
	}
}
